home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 18 / CU Amiga Magazine's Super CD-ROM 18 (1997)(EMAP Images)(GB)[!][issue 1998-01].iso / CUCD / Online / hsc / source / hsclib / size.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-11-02  |  13.9 KB  |  431 lines

  1. /*
  2.  * This source code is part of hsc, a html-preprocessor,
  3.  * Copyright (C) 1995-1997  Thomas Aglassinger
  4.  *
  5.  * This program is free software; you can redistribute it and/or modify
  6.  * it under the terms of the GNU General Public License as published by
  7.  * the Free Software Foundation; either version 2 of the License, or
  8.  * (at your option) any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  */
  20. /*
  21.  * hsclib/size.c
  22.  *
  23.  * evaluate values for WIDTH and HEIGHT from file
  24.  *
  25.  * updated:  8-Nov-1996
  26.  * created:  7-Jan-1996
  27.  */
  28.  
  29. #include "hsclib/inc_base.h"
  30.  
  31. #include "hsclib/uri.h"
  32.  
  33. /* markers for JFIF/JPEG that contain
  34.  * information about image dimension
  35.  */
  36. static UBYTE msof[] =
  37. {
  38.     /* M_SOF0  */ 0xc0,
  39.     /* M_SOF1  */ 0xc1,
  40.     /* M_SOF2  */ 0xc2,
  41.     /* M_SOF3  */ 0xc3,
  42.     /* M_SOF5  */ 0xc5,
  43.     /* M_SOF6  */ 0xc6,
  44.     /* M_SOF7  */ 0xc7,
  45.     /* M_SOF9  */ 0xc9,
  46.     /* M_SOF10 */ 0xca,
  47.     /* M_SOF11 */ 0xcb,
  48.     /* M_SOF13 */ 0xcd,
  49.     /* M_SOF14 */ 0xce,
  50.     /* M_SOF15 */ 0xcf,
  51.     /* end     */ 0x00
  52. };
  53.  
  54. /*
  55.  * fucking macro to compare fucking unsigned strings without
  56.  * fucking warnings that are only a result of the fucking
  57.  * difference in the declaration of fucking `char' between
  58.  * fucking C (by fucking K&R) and fucking C++ (by fucking
  59.  * Stroustrupp-or-whatever-the-unspellable-name-of-this-guy-is)
  60.  *
  61.  * WHY DID I NEVER HAVE SUCH PROBLEMS IN BASIC,REXX,PASCAL
  62.  * OR OBERON?
  63.  *
  64.  * Because the people who specified these languages had a brain.
  65.  *
  66.  * Where was I? Uh, back to the source code:
  67.  */
  68. #define fuck_strncmp(a,b,n) strncmp((char*)(a),(char*)(b),(n))
  69.  
  70. /*
  71.  * hsc_msg_img_corrupt
  72.  *
  73.  * display message that image is corrupt
  74.  */
  75. static VOID hsc_msg_img_corrupt(HSCPRC * hp, STRPTR cause)
  76. {
  77.     hsc_message(hp, MSG_IMG_CORRUPT, "image corrupt (%s)");
  78. }
  79.  
  80. /*
  81.  * try_set_attr
  82.  *
  83.  * if attribute exists and it's value is empty, set
  84.  * new value and update tag-attribute-string; otherwise
  85.  * kust compare the old and new value and warn if they
  86.  * differ
  87.  */
  88. static VOID try_setattr(HSCPRC * hp, HSCVAR * attr, ULONG value)
  89. {
  90.     if (attr)
  91.     {
  92.         STRPTR old_value = get_vartext(attr);
  93.         STRPTR new_value = long2str(value);
  94.         if (!old_value)
  95.         {
  96.             /* set new value */
  97.             set_vartext(attr, new_value);
  98.  
  99.             /* append attribute name and "=" */
  100.             app_estr(hp->tag_attr_str, " ");
  101.             app_estr(hp->tag_attr_str, attr->name);
  102.             app_estr(hp->tag_attr_str, "=");
  103.  
  104.             /* append quotes and value */
  105.             if ((hp->quotemode == QMODE_KEEP) || (hp->quotemode == QMODE_DOUBLE))
  106.                 app_estrch(hp->tag_attr_str, '\"');
  107.             else if (hp->quotemode == QMODE_SINGLE)
  108.                 app_estrch(hp->tag_attr_str, '\'');
  109.             app_estr(hp->tag_attr_str, long2str(value));        /* append value */
  110.             if ((hp->quotemode == QMODE_KEEP) || (hp->quotemode == QMODE_DOUBLE))
  111.                 app_estrch(hp->tag_attr_str, '\"');
  112.             else if (hp->quotemode == QMODE_SINGLE)
  113.                 app_estrch(hp->tag_attr_str, '\'');
  114.  
  115.         }
  116.         else
  117.         {
  118.             /* validate old value */
  119.             if (strcmp(old_value, new_value))
  120.             {
  121.                 hsc_message(hp, MSG_UNEX_ATTR_VALUE,
  122.                             "unexpected value for %A: expected %q, found %q",
  123.                             attr, new_value, old_value);
  124.             }
  125.         }
  126.     }
  127. }
  128.  
  129. /*
  130.  * get_attr_size
  131.  *
  132.  * tries to get values for WIDTH and HEIGHT attributes
  133.  * from file; if possible, the corresponding attributes
  134.  * for the tag passed will be set (or validated).
  135.  *
  136.  * result: TRUE, if filetype has been recognised
  137.  */
  138. BOOL get_attr_size(HSCPRC * hp, HSCTAG * tag)
  139. {
  140. #define BUFSIZE  2048
  141. #define WIDTH_PNG  16           /* file indeces for PNG */
  142. #define HEIGHT_PNG 20
  143.  
  144.     HSCVAR *asrc = tag->uri_size;
  145.     STRPTR srcuri = NULL;
  146.  
  147.     if (asrc)
  148.     {
  149.         srcuri = get_vartext(asrc);
  150.     }
  151.     else
  152.     {
  153.         panic("no uri_size");
  154.     }
  155.  
  156.     if (hp->getsize && srcuri && (uri_kind(srcuri) != URI_ext))
  157.     {
  158.         unsigned char *buf = (unsigned char *) umalloc(BUFSIZE);
  159.         EXPSTR *srcpath = init_estr(64);
  160.         EXPSTR *imgpath = init_estr(64);
  161.         ULONG width = 0;
  162.         ULONG height = 0;
  163.         BOOL transparent = FALSE;
  164.         BOOL progressive = FALSE;
  165.         STRPTR filetype = NULL;
  166.         FILE *fref = NULL;      /* file link references to */
  167.         unsigned char id_PNG[] =
  168.         {
  169.             137, 80, 78, 71, 13, 10, 26, 10
  170.         };                      /* PNG image header */
  171.  
  172.         conv_hscuri2file(hp, srcpath, srcuri);
  173.  
  174.         DSZ(fprintf(stderr, DHL "   uri : \"%s\"\n" DHL "   path: \"%s\"\n",
  175.                     srcuri, estr2str(srcpath)));
  176.  
  177.         fref = fopen(estr2str(srcpath), "r");
  178.  
  179.         if (fref)
  180.         {
  181.             /* fill buffer with zero */
  182.             memset(buf, 0, BUFSIZE);
  183.  
  184.             /* read buffer  from file */
  185.             fread(buf, BUFSIZE, 1, fref);
  186.  
  187.             if (buf[0] == 0xff)
  188.             {
  189.                 /*
  190.                  * JFIF/JPEG
  191.                  */
  192.                 BOOL found = FALSE;
  193.                 size_t i = 0;
  194.  
  195.                 /*TODO: recognize and report progressive */
  196.                 /*TODO: warning for progressive */
  197.                 while (!found && (i < BUFSIZE + 8))
  198.                 {
  199.                     if (buf[i] == 0xff)
  200.                     {
  201.                         BOOL is_msof = FALSE;
  202.                         int j = 0;
  203.  
  204.                         DSZ(fprintf(stderr,
  205.                                     "%04lx: %02x %02x: (%02x%02x %02x%02x) ",
  206.                                     (ULONG) i, buf[i], buf[i + 1],
  207.                                     buf[i + 2], buf[i + 3],
  208.                                     buf[i + 4], buf[i + 5]));
  209.  
  210.                         /* check if marker is of required type */
  211.                         while (!is_msof && msof[j])
  212.                             if (buf[i + 1] == msof[j])
  213.                                 is_msof = TRUE;
  214.                             else
  215.                                 j++;
  216.  
  217.                         if (is_msof)
  218.                         {
  219.                             DSZ(
  220.                                    {
  221.                                    for (j = 0; j < 10; j++)
  222.                                    {
  223.  
  224.                                    printf("\n  %-2d: $%02x %-3d",
  225.                                           j, buf[i + j], buf[i + j]);
  226.                                    if (buf[i + j] >= 32)
  227.                                    printf(" '%c'", buf[i + j]);
  228.  
  229.                                    }
  230.                                    }
  231.                             );
  232.  
  233.                             filetype = "JFIF/JPEG";
  234.                             width = buf[i + 8] + (buf[i + 7] << 8);
  235.                             height = buf[i + 6] + (buf[i + 5] << 8);
  236.                             found = TRUE;
  237.  
  238.                         }
  239.                         else
  240.                         {
  241.                             DDA(printf("ignore\n"));
  242.                         }
  243.                     }
  244.  
  245.                     i++;
  246.                 }
  247.  
  248.                 /* check if buffer exeeds */
  249.                 if (i >= (BUFSIZE + 8))
  250.                 {
  251.                     hsc_msg_img_corrupt(hp, "image buffer exeeds");
  252.                 }
  253.             }
  254.             else if (!fuck_strncmp("GIF87a", (STRPTR) buf, 6)
  255.                      || !fuck_strncmp("GIF89a", (STRPTR) buf, 6))
  256.             {
  257.                 /*
  258.                  * GIF
  259.                  */
  260.                 LONG use_global_colormap = (buf[10] & 0x80) >> 7;
  261.                 LONG pixeldepth = (buf[10] & 0x07) + 1;
  262.                 LONG startimg =
  263.                 13 + use_global_colormap * 3 * (1 << pixeldepth);
  264.                 BOOL fucked_up = FALSE;
  265.  
  266.                 DSZ(fprintf(stderr, DHL "  buf=%d: gcolmap=%ld, pxldep=%ld\n",
  267.                             buf[10], use_global_colormap, pixeldepth));
  268.  
  269.                 while (!fucked_up && (buf[startimg] != ','))
  270.                 {
  271.                     DSZ(fprintf(stderr, DHL "  %04lx: id=%02x\n",
  272.                                 startimg, buf[startimg]));
  273.  
  274.                     if (buf[startimg] == '!')
  275.                     {
  276.                         UBYTE blksize = 0;
  277.  
  278.                         if (buf[startimg + 1] == 0xF9)
  279.                         {
  280.                             /* graphic control extensions */
  281.                             /* check if transparent */
  282.                             transparent = (buf[startimg + 3] & 0x01);
  283.                             if (transparent)
  284.                             {
  285.                                 DDA(fprintf(stderr, DHL "  (transparent)\n"));
  286.                             }
  287.                         }
  288.  
  289.                         /* skip all blocks */
  290.                         startimg += 2;
  291.                         do
  292.                         {
  293.                             blksize = buf[startimg];
  294.                             DDA(printf("  skip block sized %d\n", blksize));
  295.                             startimg += 1L + blksize;
  296.                         }
  297.                         while (!fucked_up && (blksize));
  298.  
  299.                         /* check if buffer exeeds */
  300.                         if (startimg > (BUFSIZE + 9))
  301.                         {
  302.                             hsc_msg_img_corrupt(hp, "image buffer exeeds");
  303.                             fucked_up = TRUE;
  304.                         }
  305.  
  306.                     }
  307.                     else
  308.                     {
  309.                         hsc_msg_img_corrupt(hp, "unknown gif-block");
  310.                         DSZ(fprintf(stderr, "  id='%x', index=%ld/\n",
  311.                                     buf[startimg], startimg));
  312.                         fucked_up = TRUE;
  313.                     }
  314.                 }
  315.  
  316.                 if ((buf[startimg] != ',') && !fucked_up)
  317.                 {
  318.                     DSZ(fprintf(stderr, DHL "  %04lx: id=%02x\n",
  319.                                 startimg, buf[startimg]));
  320.                     hsc_msg_img_corrupt(hp, "image separator expected");
  321.                 }
  322.                 else
  323.                 {
  324.                     /* been sucessful */
  325.                     DSZ(fprintf(stderr, DHL "  %04lx: id=%02x\n",
  326.                                 startimg, buf[startimg]));
  327.  
  328.                     filetype = "GIF";
  329.                     width = buf[startimg + 5] + 256 * buf[startimg + 6];
  330.                     height = buf[startimg + 7] + 256 * buf[startimg + 8];
  331.                     progressive = (0 != (buf[startimg + 9] & (1 << 6)));
  332.                     DDA(fprintf(stderr,
  333.                                 DHL "  width : %lu\n"
  334.                                 DHL "  height: %lu\n",
  335.                                 width, height));
  336.                 }
  337.             }
  338.             else if (!fuck_strncmp(id_PNG, buf, 8))
  339.             {
  340.                 /*
  341.                  * PNG
  342.                  */
  343.  
  344.                 filetype = "PNG";
  345.                 width = 0x00800000 * buf[WIDTH_PNG] +
  346.                     0x00010000 * buf[WIDTH_PNG + 1] +
  347.                     0x00000100 * buf[WIDTH_PNG + 2] +
  348.                     0x00000001 * buf[WIDTH_PNG + 3];
  349.                 height = 0x00800000 * buf[HEIGHT_PNG] +
  350.                     0x00010000 * buf[HEIGHT_PNG + 1] +
  351.                     0x00000100 * buf[HEIGHT_PNG + 2] +
  352.                     0x00000001 * buf[HEIGHT_PNG + 3];
  353.  
  354.                 progressive = buf[HEIGHT_PNG + 9];
  355.                 /*TODO: transparent */
  356.  
  357. #if DEBUG_SIZE
  358.                 /* disaply whole image buffer */
  359.                 if (hp->debug)
  360.                 {
  361.                     int i;
  362.                     for (i = 0; i < BUFSIZE; i++)
  363.                     {
  364.  
  365.                         fprintf(stderr, "%-2d: $%02x %-3d", i, buf[i], buf[i]);
  366.                         if (buf[i] >= 32)
  367.                         {
  368.                             fprintf(stderr, " '%c'\n", buf[i]);
  369.                         }
  370.                         else
  371.                         {
  372.                             fprintf(stderr, "\n");
  373.                         }
  374.                     }
  375.                 }
  376. #endif
  377.                 DDA(fprintf(stderr, DHL "  width : %lu\nheight: %lu\n",
  378.                             width, height));
  379.             }
  380.             else
  381.             {
  382.                 /* unknown file type */
  383.                 hsc_message(hp, MSG_UNKN_FILETYPE,
  384.                             "filetype of %q not recognised",
  385.                             estr2str(srcpath));
  386.             }
  387.  
  388.             DSZ(fprintf(stderr, DHL "  size: \"%s\" (%ldx%ld)\n",
  389.                         filetype, width, height));
  390.  
  391.             fclose(fref);
  392.         }
  393.         else
  394.         {
  395.             DSZ(fprintf(stderr, DHL "  Can't open image `%s'\n",
  396.                         estr2str(srcpath)));
  397.             hsc_msg_nouri(hp, estr2str(srcpath), srcuri, "image-size");
  398.         }
  399.  
  400.         /* set values */
  401.         if (height && width)
  402.         {
  403.             HSCVAR *awidth = find_varname(tag->attr, "WIDTH");
  404.             HSCVAR *aheight = find_varname(tag->attr, "HEIGHT");
  405.  
  406.             /* status message */
  407.             app_estr(srcpath, ": ");
  408.             app_estr(srcpath, filetype);
  409.             app_estr(srcpath, ", ");
  410.             app_estr(srcpath, long2str(width));
  411.             app_estr(srcpath, "x");
  412.             app_estr(srcpath, long2str(height));
  413.             if (progressive)
  414.                 app_estr(srcpath, ", progressive");
  415.             if (transparent)
  416.                 app_estr(srcpath, ", transparent");
  417.             hsc_status_misc(hp, estr2str(srcpath));
  418.  
  419.             try_setattr(hp, awidth, width);
  420.             try_setattr(hp, aheight, height);
  421.         }
  422.  
  423.         /* free local resources */
  424.         ufree(buf);
  425.         del_estr(srcpath);
  426.         del_estr(imgpath);
  427.     }
  428.  
  429.     return (TRUE);
  430. }
  431.